ποΈGitΠ―ΡΠ°ποΈ
Commit ea85b906e86c00261ec91f9ad7cf4a601417d135
Parents : 9d5e20c
Author : James Rich <2199651+jamesarich@users.noreply.github.com>
Signature : Signature validation error
Date : 2026-05-20T15:57:08-07:00
Committer : GitHub <noreply@github.com>
Date : 2026-05-20T17:57:08-05:00
feat(nav): rename tab labels to canonical order (#5551)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Changes
18 files changed, 675 insertions(+), 35 deletions(-)
Diff
diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index d357d0d989..0d5c633539 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -57,6 +57,14 @@ KMP modules have different task names than pure-Android modules. Using the wrong
- **Protos**: `core/proto/` is a read-only git submodule. Never modify proto files.
- **Branches**: Must start with `feat/`, `fix/`, `chore/`, `docs/`, `build/`, `ci/`, `refactor/`, `test/`, `deps/`, or a numeric spec prefix. Always branch off `origin/main`.
+<!-- SPECKIT START -->
+## Active Plan
+
+- **Feature**: Reorder Bottom Navigation Tab Labels
+- **Plan**: `specs/20260520-153412-nav-tab-labels/plan.md`
+- **Branch**: `jamesarich/issue-5543-alignment-reorder-bottom-navigation-tab-91d55d`
+<!-- SPECKIT END -->
+
## Deeper Guidance
Consult `.skills/` for detailed playbooks:
diff --git a/.specify/feature.json b/.specify/feature.json
index 182006984e..cd2b73f689 100644
--- a/.specify/feature.json
+++ b/.specify/feature.json
@@ -1 +1 @@
-{"feature_directory":"specs/20260520-153449-node-list-context-menu"}
+{"feature_directory":"specs/20260520-153412-nav-tab-labels"}
diff --git a/androidApp/src/main/kotlin/org/meshtastic/app/ui/Main.kt b/androidApp/src/main/kotlin/org/meshtastic/app/ui/Main.kt
index ec8dab03e3..b27b300dfa 100644
--- a/androidApp/src/main/kotlin/org/meshtastic/app/ui/Main.kt
+++ b/androidApp/src/main/kotlin/org/meshtastic/app/ui/Main.kt
@@ -59,7 +59,7 @@ fun MainScreen() {
// from the StateFlow (seeded from persisted prefs) so the initial tab is set in one shot.
val initialTab =
if (viewModel.currentDeviceAddressFlow.value.isNullOrSelectedNone()) {
- TopLevelDestination.Connections.route
+ TopLevelDestination.Connect.route
} else {
NodesRoute.Nodes
}
@@ -82,7 +82,7 @@ fun MainScreen() {
scrollToTopEvents = viewModel.scrollToTopEventFlow,
onHandleDeepLink = viewModel::handleDeepLink,
onNavigateToConnections = {
- multiBackstack.navigateTopLevel(TopLevelDestination.Connections.route)
+ multiBackstack.navigateTopLevel(TopLevelDestination.Connect.route)
},
)
mapGraph(backStack)
diff --git a/core/navigation/src/commonMain/kotlin/org/meshtastic/core/navigation/MultiBackstack.kt b/core/navigation/src/commonMain/kotlin/org/meshtastic/core/navigation/MultiBackstack.kt
index 49f1f55a69..ac977c52cc 100644
--- a/core/navigation/src/commonMain/kotlin/org/meshtastic/core/navigation/MultiBackstack.kt
+++ b/core/navigation/src/commonMain/kotlin/org/meshtastic/core/navigation/MultiBackstack.kt
@@ -83,15 +83,13 @@ private val CurrentTabSaver =
TopLevelDestination.entries.indexOfFirst { it.route::class == state.value::class }.takeIf { it >= 0 }
},
restore = { ordinal ->
- mutableStateOf(
- TopLevelDestination.entries.getOrNull(ordinal)?.route ?: TopLevelDestination.Connections.route,
- )
+ mutableStateOf(TopLevelDestination.entries.getOrNull(ordinal)?.route ?: TopLevelDestination.Connect.route)
},
)
/** Remembers a [MultiBackstack] for managing independent tab navigation histories with Navigation 3. */
@Composable
-fun rememberMultiBackstack(initialTab: NavKey = TopLevelDestination.Connections.route): MultiBackstack {
+fun rememberMultiBackstack(initialTab: NavKey = TopLevelDestination.Connect.route): MultiBackstack {
val stacks = mutableMapOf<NavKey, NavBackStack<NavKey>>()
TopLevelDestination.entries.forEach { dest ->
diff --git a/core/navigation/src/commonMain/kotlin/org/meshtastic/core/navigation/TopLevelDestination.kt b/core/navigation/src/commonMain/kotlin/org/meshtastic/core/navigation/TopLevelDestination.kt
index 635ecfb7f4..27250c75a0 100644
--- a/core/navigation/src/commonMain/kotlin/org/meshtastic/core/navigation/TopLevelDestination.kt
+++ b/core/navigation/src/commonMain/kotlin/org/meshtastic/core/navigation/TopLevelDestination.kt
@@ -20,9 +20,9 @@ import androidx.navigation3.runtime.NavKey
import org.jetbrains.compose.resources.StringResource
import org.meshtastic.core.resources.Res
import org.meshtastic.core.resources.bottom_nav_settings
-import org.meshtastic.core.resources.connections
-import org.meshtastic.core.resources.conversations
+import org.meshtastic.core.resources.connect
import org.meshtastic.core.resources.map
+import org.meshtastic.core.resources.messages
import org.meshtastic.core.resources.nodes
/**
@@ -32,11 +32,11 @@ import org.meshtastic.core.resources.nodes
* and Desktop navigation shells.
*/
enum class TopLevelDestination(val label: StringResource, val route: Route) {
- Conversations(Res.string.conversations, ContactsRoute.Contacts),
+ Messages(Res.string.messages, ContactsRoute.Contacts),
Nodes(Res.string.nodes, NodesRoute.Nodes),
Map(Res.string.map, MapRoute.Map()),
Settings(Res.string.bottom_nav_settings, SettingsRoute.Settings()),
- Connections(Res.string.connections, ConnectionsRoute.Connections),
+ Connect(Res.string.connect, ConnectionsRoute.Connections),
;
companion object {
diff --git a/core/navigation/src/commonTest/kotlin/org/meshtastic/core/navigation/MultiBackstackTest.kt b/core/navigation/src/commonTest/kotlin/org/meshtastic/core/navigation/MultiBackstackTest.kt
index 4ec1f71395..ebbb5cfd43 100644
--- a/core/navigation/src/commonTest/kotlin/org/meshtastic/core/navigation/MultiBackstackTest.kt
+++ b/core/navigation/src/commonTest/kotlin/org/meshtastic/core/navigation/MultiBackstackTest.kt
@@ -85,21 +85,21 @@ class MultiBackstackTest {
@Test
fun `goBack on root of non-start tab returns to start tab`() {
- val startTab = TopLevelDestination.Connections.route
+ val startTab = TopLevelDestination.Connect.route
val multiBackstack = createMultiBackstack(startTab)
val mapStack = NavBackStack<NavKey>().apply { addAll(listOf(TopLevelDestination.Map.route)) }
- val connectionsStack = NavBackStack<NavKey>().apply { addAll(listOf(TopLevelDestination.Connections.route)) }
+ val connectStack = NavBackStack<NavKey>().apply { addAll(listOf(TopLevelDestination.Connect.route)) }
multiBackstack.backStacks =
- mapOf(TopLevelDestination.Map.route to mapStack, TopLevelDestination.Connections.route to connectionsStack)
+ mapOf(TopLevelDestination.Map.route to mapStack, TopLevelDestination.Connect.route to connectStack)
multiBackstack.navigateTopLevel(TopLevelDestination.Map.route)
assertEquals(TopLevelDestination.Map.route, multiBackstack.currentTabRoute)
multiBackstack.goBack()
- assertEquals(TopLevelDestination.Connections.route, multiBackstack.currentTabRoute)
+ assertEquals(TopLevelDestination.Connect.route, multiBackstack.currentTabRoute)
}
@Test
@@ -120,21 +120,18 @@ class MultiBackstackTest {
@Test
fun `handleDeepLink from different tab switches tab and sets stack`() {
- // Start on Connections tab
- val startTab = TopLevelDestination.Connections.route
+ // Start on Connect tab
+ val startTab = TopLevelDestination.Connect.route
val multiBackstack = createMultiBackstack(startTab)
- val connectionsStack = NavBackStack<NavKey>().apply { addAll(listOf(TopLevelDestination.Connections.route)) }
+ val connectStack = NavBackStack<NavKey>().apply { addAll(listOf(TopLevelDestination.Connect.route)) }
val nodesStack = NavBackStack<NavKey>().apply { addAll(listOf(TopLevelDestination.Nodes.route)) }
multiBackstack.backStacks =
- mapOf(
- TopLevelDestination.Connections.route to connectionsStack,
- TopLevelDestination.Nodes.route to nodesStack,
- )
+ mapOf(TopLevelDestination.Connect.route to connectStack, TopLevelDestination.Nodes.route to nodesStack)
- // Verify we start on Connections
- assertEquals(TopLevelDestination.Connections.route, multiBackstack.currentTabRoute)
+ // Verify we start on Connect
+ assertEquals(TopLevelDestination.Connect.route, multiBackstack.currentTabRoute)
// Deep-link to a TracerouteMap on the Nodes tab (this is the exact pattern
// MeshtasticAppShell uses for traceroute alert "View on Map")
diff --git a/core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/component/MeshtasticNavigationSuite.kt b/core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/component/MeshtasticNavigationSuite.kt
index 5fa55b0403..2f86e1efed 100644
--- a/core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/component/MeshtasticNavigationSuite.kt
+++ b/core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/component/MeshtasticNavigationSuite.kt
@@ -150,7 +150,7 @@ private fun handleNavigation(
}
}
- TopLevelDestination.Conversations -> {
+ TopLevelDestination.Messages -> {
val onConversationsList = currentKey is ContactsRoute.Contacts
if (!onConversationsList) {
multiBackstack.navigateTopLevel(destination.route)
@@ -180,7 +180,7 @@ private fun NavigationIconContent(
selectedDevice: String?,
uiViewModel: UIViewModel,
) {
- val isConnectionsRoute = destination == TopLevelDestination.Connections
+ val isConnectionsRoute = destination == TopLevelDestination.Connect
TooltipBox(
positionProvider = TooltipDefaults.rememberTooltipPositionProvider(TooltipAnchorPosition.Above),
@@ -211,7 +211,7 @@ private fun NavigationIconContent(
} else {
BadgedBox(
badge = {
- if (destination == TopLevelDestination.Conversations) {
+ if (destination == TopLevelDestination.Messages) {
var lastNonZeroCount by remember { mutableIntStateOf(unreadMessageCount) }
if (unreadMessageCount > 0) {
lastNonZeroCount = unreadMessageCount
diff --git a/core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/navigation/TopLevelDestinationExt.kt b/core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/navigation/TopLevelDestinationExt.kt
index dacc6ad48b..640b4ba871 100644
--- a/core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/navigation/TopLevelDestinationExt.kt
+++ b/core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/navigation/TopLevelDestinationExt.kt
@@ -29,9 +29,9 @@ import org.meshtastic.core.resources.ic_wifi
val TopLevelDestination.icon: DrawableResource
get() =
when (this) {
- TopLevelDestination.Conversations -> Res.drawable.ic_forum
+ TopLevelDestination.Messages -> Res.drawable.ic_forum
TopLevelDestination.Nodes -> Res.drawable.ic_nodes
TopLevelDestination.Map -> Res.drawable.ic_map
TopLevelDestination.Settings -> Res.drawable.ic_settings
- TopLevelDestination.Connections -> Res.drawable.ic_wifi
+ TopLevelDestination.Connect -> Res.drawable.ic_wifi
}
diff --git a/desktopApp/src/main/kotlin/org/meshtastic/desktop/Main.kt b/desktopApp/src/main/kotlin/org/meshtastic/desktop/Main.kt
index 1d0e0190e7..f8ad965083 100644
--- a/desktopApp/src/main/kotlin/org/meshtastic/desktop/Main.kt
+++ b/desktopApp/src/main/kotlin/org/meshtastic/desktop/Main.kt
@@ -285,7 +285,7 @@ private fun ApplicationScope.MeshtasticWindow(
rememberMultiBackstack(
// Land on Connections for first-run / no-device-selected; otherwise on Nodes.
if (uiViewModel.currentDeviceAddressFlow.value.let { it.isNullOrBlank() || it == "n" }) {
- TopLevelDestination.Connections.route
+ TopLevelDestination.Connect.route
} else {
TopLevelDestination.Nodes.route
},
@@ -360,7 +360,7 @@ private fun handleKeyboardShortcut(
}
Key.One -> {
- multiBackstack.navigateTopLevel(TopLevelDestination.Conversations.route)
+ multiBackstack.navigateTopLevel(TopLevelDestination.Messages.route)
true
}
@@ -375,7 +375,7 @@ private fun handleKeyboardShortcut(
}
Key.Four -> {
- multiBackstack.navigateTopLevel(TopLevelDestination.Connections.route)
+ multiBackstack.navigateTopLevel(TopLevelDestination.Connect.route)
true
}
diff --git a/desktopApp/src/main/kotlin/org/meshtastic/desktop/navigation/DesktopNavigation.kt b/desktopApp/src/main/kotlin/org/meshtastic/desktop/navigation/DesktopNavigation.kt
index 83494ce00f..6103ffdbf6 100644
--- a/desktopApp/src/main/kotlin/org/meshtastic/desktop/navigation/DesktopNavigation.kt
+++ b/desktopApp/src/main/kotlin/org/meshtastic/desktop/navigation/DesktopNavigation.kt
@@ -47,7 +47,7 @@ fun EntryProviderScope<NavKey>.desktopNavGraph(
backStack = backStack,
scrollToTopEvents = uiViewModel.scrollToTopEventFlow,
onHandleDeepLink = uiViewModel::handleDeepLink,
- onNavigateToConnections = { multiBackstack.navigateTopLevel(TopLevelDestination.Connections.route) },
+ onNavigateToConnections = { multiBackstack.navigateTopLevel(TopLevelDestination.Connect.route) },
)
contactsGraph(backStack, uiViewModel.scrollToTopEventFlow)
mapGraph(backStack)
diff --git a/desktopApp/src/test/kotlin/org/meshtastic/desktop/ui/DesktopTopLevelDestinationParityTest.kt b/desktopApp/src/test/kotlin/org/meshtastic/desktop/ui/DesktopTopLevelDestinationParityTest.kt
index ac81053ef1..1e8ffed2f0 100644
--- a/desktopApp/src/test/kotlin/org/meshtastic/desktop/ui/DesktopTopLevelDestinationParityTest.kt
+++ b/desktopApp/src/test/kotlin/org/meshtastic/desktop/ui/DesktopTopLevelDestinationParityTest.kt
@@ -30,8 +30,8 @@ import kotlin.test.assertEquals
import kotlin.test.assertFalse
/**
- * Keeps Desktop top-level destinations aligned with Android top-level navigation (Conversations, Nodes, Map, Settings,
- * Connections).
+ * Keeps Desktop top-level destinations aligned with Android top-level navigation (Messages, Nodes, Map, Settings,
+ * Connect).
*/
class DesktopTopLevelDestinationParityTest {
diff --git a/specs/20260520-153412-nav-tab-labels/checklists/requirements.md b/specs/20260520-153412-nav-tab-labels/checklists/requirements.md
new file mode 100644
index 0000000000..69664c280f
--- /dev/null
+++ b/specs/20260520-153412-nav-tab-labels/checklists/requirements.md
@@ -0,0 +1,36 @@
+# Specification Quality Checklist: Reorder Bottom Navigation Tab Labels
+
+**Purpose**: Validate specification completeness and quality before proceeding to planning
+**Created**: 2025-05-20
+**Feature**: [spec.md](../spec.md)
+
+## Content Quality
+
+- [x] No implementation details (languages, frameworks, APIs)
+- [x] Focused on user value and business needs
+- [x] Written for non-technical stakeholders
+- [x] All mandatory sections completed
+
+## Requirement Completeness
+
+- [x] No [NEEDS CLARIFICATION] markers remain
+- [x] Requirements are testable and unambiguous
+- [x] Success criteria are measurable
+- [x] Success criteria are technology-agnostic (no implementation details)
+- [x] All acceptance scenarios are defined
+- [x] Edge cases are identified
+- [x] Scope is clearly bounded
+- [x] Dependencies and assumptions identified
+
+## Feature Readiness
+
+- [x] All functional requirements have clear acceptance criteria
+- [x] User scenarios cover primary flows
+- [x] Feature meets measurable outcomes defined in Success Criteria
+- [x] No implementation details leak into specification
+
+## Notes
+
+- All items pass. Specification is ready for `/speckit.clarify` or `/speckit.plan`.
+- This is a straightforward label rename with well-defined scope and clear acceptance criteria.
+- No [NEEDS CLARIFICATION] markers were needed β the issue description fully specifies the required changes.
diff --git a/specs/20260520-153412-nav-tab-labels/data-model.md b/specs/20260520-153412-nav-tab-labels/data-model.md
new file mode 100644
index 0000000000..efd2862e37
--- /dev/null
+++ b/specs/20260520-153412-nav-tab-labels/data-model.md
@@ -0,0 +1,60 @@
+# Data Model: Nav Tab Labels Rename
+
+**Feature**: Reorder Bottom Navigation Tab Labels
+**Date**: 2026-05-20
+
+## Entities
+
+### TopLevelDestination (Enum)
+
+The shared enum defining the canonical set of top-level navigation destinations.
+
+| Entry | Label Resource | Route | Position |
+|-------|---------------|-------|----------|
+| `Messages` | `Res.string.messages` | `ContactsRoute.Contacts` | 1 |
+| `Nodes` | `Res.string.nodes` | `NodesRoute.Nodes` | 2 |
+| `Map` | `Res.string.map` | `MapRoute.Map()` | 3 |
+| `Settings` | `Res.string.bottom_nav_settings` | `SettingsRoute.Settings()` | 4 |
+| `Connect` | `Res.string.connect` | `ConnectionsRoute.Connections` | 5 |
+
+**Changes from current**:
+- `Conversations` β `Messages` (entry rename, label resource changes)
+- `Connections` β `Connect` (entry rename, label resource changes)
+
+### String Resources (New Keys)
+
+| Key | Value (English) | Usage |
+|-----|----------------|-------|
+| `messages` | `Messages` | Tab label for Messages destination |
+| `connect` | `Connect` | Tab label for Connect destination |
+
+### String Resources (Retained β No Changes)
+
+| Key | Value (English) | Usage |
+|-----|----------------|-------|
+| `conversations` | `Conversations` | Screen title in Contacts.kt |
+| `connections` | `Connection` | Screen title in ConnectionsScreen.kt |
+
+## Relationships
+
+```
+TopLevelDestination.Messages
+ βββ label β Res.string.messages (NEW)
+ βββ route β ContactsRoute.Contacts (UNCHANGED)
+ βββ icon β Res.drawable.ic_forum (UNCHANGED, via TopLevelDestinationExt)
+
+TopLevelDestination.Connect
+ βββ label β Res.string.connect (NEW)
+ βββ route β ConnectionsRoute.Connections (UNCHANGED)
+ βββ icon β Res.drawable.ic_wifi (UNCHANGED, via TopLevelDestinationExt)
+```
+
+## State Transitions
+
+N/A β No state machines affected. The enum is purely declarative.
+
+## Validation Rules
+
+- Tab order MUST remain: Messages (0), Nodes (1), Map (2), Settings (3), Connect (4)
+- Enum ordinal positions MUST NOT change (preserves `MultiBackstack` ordinal-based fallback)
+- Route objects MUST NOT change (preserves navigation, deep links, state restoration)
diff --git a/specs/20260520-153412-nav-tab-labels/plan.md b/specs/20260520-153412-nav-tab-labels/plan.md
new file mode 100644
index 0000000000..34d2a03398
--- /dev/null
+++ b/specs/20260520-153412-nav-tab-labels/plan.md
@@ -0,0 +1,79 @@
+# Implementation Plan: Reorder Bottom Navigation Tab Labels
+
+**Branch**: `jamesarich/issue-5543-alignment-reorder-bottom-navigation-tab-91d55d` | **Date**: 2026-05-20 | **Spec**: [spec.md](./spec.md)
+**Input**: Feature specification from `specs/20260520-153412-nav-tab-labels/spec.md`
+
+## Summary
+
+Rename two bottom navigation tab labels from "Conversations" β "Messages" and "Connections" β "Connect" to match the cross-platform canonical naming convention from the Menu Alignment Audit. Implementation involves: renaming the `TopLevelDestination` enum entries, adding new string resource keys for tab labels, and updating all references across the KMP codebase. Existing string keys are retained for screen titles.
+
+## Technical Context
+
+**Language/Version**: Kotlin 2.3+ / JDK 21
+**Primary Dependencies**: Compose Multiplatform, Navigation 3, Koin 4.2+
+**Storage**: N/A (string resource change only)
+**Testing**: `./gradlew allTests` (KMP commonTest), `./gradlew test` (Android-only)
+**Target Platform**: Android (mobile), Desktop (JVM) β KMP shared code
+**Project Type**: Mobile app (KMP multiplatform)
+**Performance Goals**: N/A (label change only, no runtime impact)
+**Constraints**: Must not break navigation routing, deep links, or state restoration
+**Scale/Scope**: 7 files modified across 3 modules (`core:navigation`, `core:ui`, `core:resources`) + test updates
+
+## Constitution Check
+
+*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
+
+- **I. Kotlin Multiplatform Core**: β
All changes are in `commonMain` source sets (`core/navigation`, `core/ui`, `core/resources`). No platform-specific (`androidMain`/`desktopMain`) code is modified. Enum rename and string resources are shared across all targets.
+- **II. Zero Lint Tolerance**: β
Will run: `./gradlew spotlessApply spotlessCheck detekt` for all touched modules. After adding string resources: `python3 scripts/sort-strings.py`.
+- **III. Compose Multiplatform UI**: β
No new UI composables introduced. The `MeshtasticNavigationSuite` already uses `TopLevelDestination.label` via `stringResource()`; the label change is purely data-driven. No float formatting involved.
+- **IV. Privacy First**: β
No PII, location data, or cryptographic keys involved. `core/proto` submodule is not touched.
+- **V. Design Standards Compliance**: β
This change directly implements the [Menu Alignment Audit](https://github.com/meshtastic/design/blob/master/standards/audits/menu-alignment-audit.md) from `meshtastic/design`. Cross-platform behavior spec is the audit itself.
+- **VI. Documentation Freshness**: β
No doc pages require updates β this is a label rename with no feature behavior change. Existing docs reference screen functionality, not tab label text.
+- **VII. Verify Before Push**: Will run:
+ ```bash
+ ./gradlew spotlessApply spotlessCheck detekt assembleDebug test allTests
+ python3 scripts/sort-strings.py
+ ```
+ Post-push: `gh pr checks <PR>` or `gh run list --branch jamesarich/issue-5543-alignment-reorder-bottom-navigation-tab-91d55d --limit 5`
+
+## Project Structure
+
+### Documentation (this feature)
+
+```text
+specs/20260520-153412-nav-tab-labels/
+βββ plan.md # This file
+βββ research.md # Phase 0 output
+βββ data-model.md # Phase 1 output
+βββ quickstart.md # Phase 1 output
+βββ tasks.md # Phase 2 output (via /speckit.tasks)
+```
+
+### Source Code (repository root)
+
+```text
+core/
+βββ navigation/src/commonMain/kotlin/org/meshtastic/core/navigation/
+β βββ TopLevelDestination.kt # Enum entries renamed
+β βββ MultiBackstack.kt # References updated
+βββ navigation/src/commonTest/kotlin/org/meshtastic/core/navigation/
+β βββ MultiBackstackTest.kt # Test references updated
+βββ ui/src/commonMain/kotlin/org/meshtastic/core/ui/
+β βββ navigation/TopLevelDestinationExt.kt # Icon mapping updated
+β βββ component/MeshtasticNavigationSuite.kt # References updated
+βββ resources/src/commonMain/composeResources/values/
+β βββ strings.xml # New keys: messages, connect
+androidApp/src/main/kotlin/org/meshtastic/app/ui/
+β βββ Main.kt # References updated
+desktopApp/src/main/kotlin/org/meshtastic/desktop/
+β βββ Main.kt # References updated
+β βββ navigation/DesktopNavigation.kt # References updated
+desktopApp/src/test/kotlin/org/meshtastic/desktop/ui/
+β βββ DesktopTopLevelDestinationParityTest.kt # May need update
+```
+
+**Structure Decision**: Kotlin Multiplatform with shared `commonMain` source sets. All changes are in existing files; no new modules or directories created.
+
+## Complexity Tracking
+
+> No constitution violations. All gates pass.
diff --git a/specs/20260520-153412-nav-tab-labels/quickstart.md b/specs/20260520-153412-nav-tab-labels/quickstart.md
new file mode 100644
index 0000000000..d7a0e4480c
--- /dev/null
+++ b/specs/20260520-153412-nav-tab-labels/quickstart.md
@@ -0,0 +1,63 @@
+# Quickstart: Nav Tab Labels Rename
+
+**Feature**: Reorder Bottom Navigation Tab Labels
+**Date**: 2026-05-20
+
+## Overview
+
+This feature renames two `TopLevelDestination` enum entries and their associated string resources to align with the Meshtastic cross-platform Menu Alignment Audit.
+
+## Implementation Steps (High-Level)
+
+### Step 1: Add String Resources
+
+Add two new keys to `core/resources/src/commonMain/composeResources/values/strings.xml`:
+```xml
+<string name="connect">Connect</string>
+<string name="messages">Messages</string>
+```
+
+Then run: `python3 scripts/sort-strings.py`
+
+### Step 2: Rename Enum Entries
+
+In `core/navigation/src/commonMain/kotlin/org/meshtastic/core/navigation/TopLevelDestination.kt`:
+- `Conversations(Res.string.conversations, ...)` β `Messages(Res.string.messages, ...)`
+- `Connections(Res.string.connections, ...)` β `Connect(Res.string.connect, ...)`
+
+Update imports accordingly.
+
+### Step 3: Update All References
+
+Files requiring mechanical rename of `TopLevelDestination.Conversations` β `.Messages` and `.Connections` β `.Connect`:
+
+1. `core/ui/.../TopLevelDestinationExt.kt` β icon `when` branches
+2. `core/ui/.../MeshtasticNavigationSuite.kt` β any explicit references
+3. `core/navigation/.../MultiBackstack.kt` β default tab reference
+4. `core/navigation/src/commonTest/.../MultiBackstackTest.kt` β test setup
+5. `androidApp/.../Main.kt` β Android entry point
+6. `desktopApp/.../Main.kt` β Desktop entry point
+7. `desktopApp/.../DesktopNavigation.kt` β Desktop nav shell
+
+### Step 4: Verify
+
+```bash
+./gradlew spotlessApply spotlessCheck detekt assembleDebug test allTests
+```
+
+## Key Decisions
+
+| Decision | Rationale |
+|----------|-----------|
+| New string keys (not reusing old) | Old keys used as screen titles elsewhere |
+| Enum entry rename (not just label) | Code clarity + spec requirement |
+| No route changes | Preserves deep links & state restoration |
+| No localization changes | Deferred to Crowdin sync cycle |
+
+## Risks & Mitigations
+
+| Risk | Mitigation |
+|------|-----------|
+| Missed reference causes compile error | IDE rename refactoring + full `allTests` build |
+| Ordinal shift breaks MultiBackstack | Entries stay in same position β order unchanged |
+| Localized users see English fallback | Expected behavior for new keys until Crowdin sync |
diff --git a/specs/20260520-153412-nav-tab-labels/research.md b/specs/20260520-153412-nav-tab-labels/research.md
new file mode 100644
index 0000000000..32f9dddc19
--- /dev/null
+++ b/specs/20260520-153412-nav-tab-labels/research.md
@@ -0,0 +1,78 @@
+# Research: Nav Tab Labels Rename
+
+**Feature**: Reorder Bottom Navigation Tab Labels
+**Date**: 2026-05-20
+
+## Research Tasks
+
+### 1. Enum Rename Impact on Serialization / State Restoration
+
+**Decision**: Renaming `TopLevelDestination.Conversations` β `Messages` and `TopLevelDestination.Connections` β `Connect` is safe for navigation state.
+
+**Rationale**:
+- Navigation state is keyed by `NavKey` route objects (e.g., `ContactsRoute.Contacts`, `ConnectionsRoute.Connections`), NOT by enum entry names.
+- The `TopLevelDestination.route` property maps to typed route objects β the enum name is never serialized.
+- `MultiBackstack` stores `NavKey` instances in its back stack maps, keyed by route class identity (`it::class == dest.route::class`).
+- Process death restoration uses `SavedStateHandle` with route objects, not enum string names.
+
+**Alternatives Considered**:
+- Keep old enum names and only change labels: Rejected because the spec explicitly requires renaming entries for code clarity and alignment with the canonical naming.
+
+### 2. String Resource Key Strategy
+
+**Decision**: Add new keys `messages` and `connect` for tab labels. Retain existing keys `conversations` and `connections` for screen titles.
+
+**Rationale**:
+- `conversations` is used in `Contacts.kt` for the screen title (confirmed from spec clarification session).
+- `connections` is used in `ConnectionsScreen.kt` for the screen/section title.
+- Separating tab label keys from screen title keys allows independent localization and prevents unintended label changes elsewhere.
+- The `connections` key currently has value "Connection" (singular) β this is a screen title, not a tab label.
+
+**Alternatives Considered**:
+- Reuse existing keys and rename their values: Rejected because it would change screen titles in feature modules that are out of scope.
+- Use `tab_messages` / `tab_connect` prefixed keys: Rejected in favor of simpler `messages` / `connect` per clarification decision.
+
+### 3. Compose Resource Import Changes
+
+**Decision**: After adding `messages` and `connect` to `strings.xml`, the generated `Res.string.messages` and `Res.string.connect` accessors will be available after a build.
+
+**Rationale**:
+- Compose Multiplatform generates accessor objects from resource keys at compile time.
+- Import statements in `TopLevelDestination.kt` will change from `org.meshtastic.core.resources.conversations` / `org.meshtastic.core.resources.connections` to `org.meshtastic.core.resources.messages` / `org.meshtastic.core.resources.connect`.
+- Old imports (`conversations`, `connections`) remain valid since those keys are retained β they just won't be used in `TopLevelDestination.kt` anymore.
+
+**Alternatives Considered**: None β this is the standard Compose Resources workflow.
+
+### 4. Test Impact Assessment
+
+**Decision**: Update `MultiBackstackTest.kt` references from `TopLevelDestination.Connections` to `TopLevelDestination.Connect`. The `DesktopTopLevelDestinationParityTest.kt` tests enum parity generically (iterates `entries`) and requires no changes.
+
+**Rationale**:
+- `MultiBackstackTest.kt` explicitly references `TopLevelDestination.Connections` in 8 locations for default tab setup.
+- The parity test uses `TopLevelDestination.entries` enumeration, so it adapts automatically to renamed entries.
+- No test logic changes needed β only identifier renames.
+
+**Alternatives Considered**: None β mechanical rename with no behavioral changes.
+
+### 5. Sort Script for String Resources
+
+**Decision**: Run `python3 scripts/sort-strings.py` after adding new keys to maintain alphabetical ordering.
+
+**Rationale**:
+- Constitution (Development Workflow) mandates running this script after any string resource addition.
+- Keys `connect` and `messages` will be inserted alphabetically by the script.
+- `strings-index.txt` will be regenerated automatically.
+
+**Alternatives Considered**: None β this is a mandatory workflow step.
+
+## Summary of Resolved Items
+
+| Item | Resolution |
+|------|-----------|
+| Enum rename breaks state? | No β routes use typed objects, not enum names |
+| String key strategy | New keys `messages`/`connect`; old keys retained |
+| Import changes | Mechanical β generated accessors update on build |
+| Test updates needed | `MultiBackstackTest.kt` identifier renames only |
+| Post-change workflow | `python3 scripts/sort-strings.py` required |
+
+All NEEDS CLARIFICATION items resolved. No open questions remain.
diff --git a/specs/20260520-153412-nav-tab-labels/spec.md b/specs/20260520-153412-nav-tab-labels/spec.md
new file mode 100644
index 0000000000..4ffeb41d26
--- /dev/null
+++ b/specs/20260520-153412-nav-tab-labels/spec.md
@@ -0,0 +1,157 @@
+# Feature Specification: Reorder Bottom Navigation Tab Labels
+
+**Feature Branch**: `jamesarich/issue-5543-alignment-reorder-bottom-navigation-tab-91d55d`
+**Created**: 2025-05-20
+**Status**: Draft
+**Input**: User description: "Issue #5543 - Reorder bottom navigation tabs to canonical order per Menu Alignment Audit"
+**Cross-Platform Spec**: [Menu Alignment Audit](https://github.com/meshtastic/design/blob/master/standards/audits/menu-alignment-audit.md)
+
+## Clarifications
+
+### Session 2026-05-20
+
+- Q: Should string resource keys be renamed (not just display values)? β A: Yes β create new keys `messages` and `connect` for nav tab labels. Old keys (`conversations`, `connections`) remain for screen titles in Contacts.kt and ConnectionsScreen.kt.
+- Q: Should localized strings.xml files be updated in this PR? β A: No β defer to Crowdin. Only update English `values/strings.xml`; localized files pick up new keys in next translation sync.
+
+## Summary
+
+Rename two bottom navigation tab labels to match the cross-platform canonical naming convention defined in the Meshtastic Menu Alignment Audit. "Conversations" becomes "Messages" and "Connections" becomes "Connect". Tab order already matches the canonical order and requires no positional changes.
+
+## Goals
+
+1. Achieve cross-platform label consistency by aligning Android tab names with the canonical standard
+2. Improve user familiarity by using industry-standard terminology ("Messages" for messaging)
+3. Reduce cognitive friction for users switching between Meshtastic clients on different platforms
+4. Maintain existing navigation behavior and tab ordering without regressions
+
+## Non-Goals
+
+- Changing the tab order (already matches canonical: Messages, Nodes, Map, Settings, Connect)
+- Redesigning tab icons or visual styling
+- Adding, removing, or merging navigation tabs
+- Changing functionality behind any tab
+- Modifying navigation deep link route identifiers (only user-visible labels change)
+
+## User Scenarios & Testing *(mandatory)*
+
+### User Story 1 - See Updated Tab Labels (Priority: P1)
+
+As a Meshtastic Android user, I see "Messages" and "Connect" as tab labels so that the interface matches documentation and other platform clients.
+
+**Why this priority**: This is the core deliverable β the visual label change that achieves cross-platform alignment.
+
+**Independent Test**: Open the app after update; visually confirm bottom navigation bar shows "Messages" (position 1) and "Connect" (position 5).
+
+**Acceptance Scenarios**:
+
+1. **Given** the app is launched, **When** the bottom navigation bar is visible, **Then** the first tab reads "Messages" (not "Conversations")
+2. **Given** the app is launched, **When** the bottom navigation bar is visible, **Then** the fifth tab reads "Connect" (not "Connections")
+3. **Given** the app is launched, **When** the bottom navigation bar is visible, **Then** tab order is: Messages, Nodes, Map, Settings, Connect
+
+---
+
+### User Story 2 - Navigation Still Functions After Rename (Priority: P1)
+
+As a user, I can tap the renamed tabs and navigate to the correct screens without any change in behavior.
+
+**Why this priority**: Equal to P1 because broken navigation would be a blocking regression.
+
+**Independent Test**: Tap "Messages" tab β messaging screen loads; tap "Connect" tab β connection/pairing screen loads.
+
+**Acceptance Scenarios**:
+
+1. **Given** the user is on any screen, **When** they tap "Messages", **Then** the messaging/conversations screen appears
+2. **Given** the user is on any screen, **When** they tap "Connect", **Then** the device connection/pairing screen appears
+3. **Given** the user taps between all five tabs in rapid succession, **When** each tab is selected, **Then** the correct corresponding screen displays without delay or error
+
+---
+
+### User Story 3 - Deep Links and State Restoration Work (Priority: P2)
+
+As a user who receives a notification or restores the app from background, deep links and saved navigation state continue to route correctly.
+
+**Why this priority**: Ensures no regression in system-level navigation behavior that relies on route identifiers.
+
+**Independent Test**: Trigger a message notification β tap it β app opens to the messaging screen. Kill and restore the app β previously selected tab is restored.
+
+**Acceptance Scenarios**:
+
+1. **Given** the app is in the background and a message notification arrives, **When** the user taps the notification, **Then** the app navigates to the messaging screen (now labeled "Messages")
+2. **Given** the user is on the "Connect" tab and the system kills the app, **When** the app is restored, **Then** the "Connect" tab is selected and the connection screen is displayed
+3. **Given** a deep link targets the messaging section, **When** the link is activated, **Then** the app navigates to the messaging screen under the "Messages" tab
+
+---
+
+### Edge Cases
+
+- What happens if a user has the old version cached and updates? Label change takes effect immediately as it is a string resource change.
+- How does the app behave with localized strings? Localized translations for these labels should also be updated for all supported languages.
+- What about accessibility services (TalkBack)? The new labels ("Messages", "Connect") are announced correctly by screen readers since they derive from the same string resources.
+
+## Architecture
+
+### Key Components
+
+| Component | Module / File | Purpose |
+|-----------|---------------|---------|
+| Navigation bar strings | `core/resources/src/commonMain/composeResources/values/strings.xml` | New keys `messages` and `connect` for tab labels; old keys retained for screen titles |
+| Localized strings | `core/resources/src/commonMain/composeResources/values-*/strings.xml` | Deferred β new keys picked up in next Crowdin sync |
+| Bottom navigation composable | Navigation component referencing string resources | Displays tab labels in bottom bar |
+
+## Requirements *(mandatory)*
+
+### Functional Requirements
+
+- **FR-001**: The bottom navigation tab currently labeled "Conversations" MUST display "Messages" in English locale
+- **FR-002**: The bottom navigation tab currently labeled "Connections" (or "Connection") MUST display "Connect" in English locale
+- **FR-003**: Tab order MUST remain: Messages, Nodes, Map, Settings, Connect (positions 1β5)
+- **FR-004**: Tapping any renamed tab MUST navigate to the same destination screen as before the rename
+- **FR-005**: Deep links that previously routed to the Conversations or Connections screens MUST continue to function
+- **FR-006**: State restoration MUST correctly restore the selected tab after process death
+
+### Non-Functional Requirements
+
+- **NFR-001**: Accessibility β screen readers MUST announce the updated labels ("Messages", "Connect") when tabs receive focus
+- **NFR-002**: Localization β translated string values are deferred to next Crowdin sync; only English `values/strings.xml` is updated in this change
+- **NFR-003**: No user-perceivable performance impact from the label change
+
+## Source-Set Impact
+
+| Source Set | Impact | Justification |
+|-----------|--------|---------------|
+| `commonMain` | Modified string resources | Tab labels are defined in shared compose resources |
+| `androidMain` | None | No platform-specific changes needed |
+| `jvmMain` | None | No desktop-specific changes needed |
+
+## Design Standards Compliance
+
+- [x] New screens reviewed against design standards β No new screens; existing screens unchanged
+- [x] M3 component selection verified β No component changes
+- [ ] Accessibility: TalkBack semantics, touch targets, color-independent info β Verify renamed labels are announced correctly
+- [x] Typography: No typography changes
+
+## Privacy Assessment
+
+- [x] No PII, location data, or cryptographic keys logged or exposed
+- [x] No new network calls that transmit user data
+- [x] Proto submodule (`core/proto`) not modified (read-only upstream)
+
+## Success Criteria *(mandatory)*
+
+### Measurable Outcomes
+
+- **SC-001**: 100% of users see "Messages" as the first tab label after updating the app
+- **SC-002**: 100% of users see "Connect" as the fifth tab label after updating the app
+- **SC-003**: Tab order matches canonical sequence (Messages, Nodes, Map, Settings, Connect) across all locales
+- **SC-004**: Zero navigation regressions β all existing deep links and state restoration paths continue to function
+- **SC-005**: Cross-platform label parity achieved β Android tab names match the Menu Alignment Audit specification
+
+## Assumptions
+
+- All business logic and UI composables reside in `commonMain` source set
+- String resources are defined in `core/resources/src/commonMain/composeResources/values/strings.xml`
+- New string resource keys (`messages`, `connect`) will be created for bottom navigation tab labels; existing keys (`conversations`, `connections`) are retained for screen titles in feature modules (Contacts.kt, ConnectionsScreen.kt)
+- Tab order is already correct (positions 1β5 match canonical) and no reordering logic changes are needed
+- Navigation route identifiers are independent of user-visible label strings (routes use programmatic keys, not display text)
+- Localized translations are deferred to the next Crowdin translation sync cycle (not in-scope for this PR)
+- The `doc_title_connections` string resource (used elsewhere, e.g., documentation titles) may need separate evaluation but is out of scope for this tab label change
diff --git a/specs/20260520-153412-nav-tab-labels/tasks.md b/specs/20260520-153412-nav-tab-labels/tasks.md
new file mode 100644
index 0000000000..73c7e0a5d8
--- /dev/null
+++ b/specs/20260520-153412-nav-tab-labels/tasks.md
@@ -0,0 +1,164 @@
+# Tasks: Reorder Bottom Navigation Tab Labels
+
+**Input**: Design documents from `specs/20260520-153412-nav-tab-labels/`
+**Prerequisites**: plan.md β
, spec.md β
, research.md β
, data-model.md β
, quickstart.md β
+
+**Tests**: No new automated tests requested in the feature specification. Existing tests will be updated to reflect the rename but no new test coverage is added.
+
+**Verification**: Constitution-required validation tasks are included for formatting, static analysis, and compile/test commands.
+
+## Format: `[ID] [P?] [Story] Description`
+
+- **[P]**: Can run in parallel (different files, no dependencies)
+- **[Story]**: Which user story this task belongs to (e.g., US1, US2, US3)
+- Include exact file paths in descriptions
+
+---
+
+## Phase 1: Setup (String Resources)
+
+**Purpose**: Add new string resource keys required by all subsequent tasks
+
+- [X] T001 Add `messages` and `connect` string keys to `core/resources/src/commonMain/composeResources/values/strings.xml`
+- [X] T002 Run `python3 scripts/sort-strings.py` to maintain alphabetical ordering and regenerate strings-index.txt
+
+---
+
+## Phase 2: Foundational (Enum Rename)
+
+**Purpose**: Rename the `TopLevelDestination` enum entries β this BLOCKS all reference updates
+
+**β οΈ CRITICAL**: No reference update tasks can begin until this phase is complete
+
+- [X] T003 Rename `Conversations` β `Messages` and `Connections` β `Connect` in `core/navigation/src/commonMain/kotlin/org/meshtastic/core/navigation/TopLevelDestination.kt` β update label resource references from `Res.string.conversations` β `Res.string.messages` and `Res.string.connections` β `Res.string.connect`
+
+**Checkpoint**: Enum entries renamed β reference updates can now proceed in parallel
+
+---
+
+## Phase 3: User Story 1 β See Updated Tab Labels (Priority: P1) π― MVP
+
+**Goal**: Bottom navigation bar displays "Messages" (position 1) and "Connect" (position 5) as tab labels
+
+**Independent Test**: Launch the app β visually confirm bottom navigation shows "Messages" and "Connect" in correct positions
+
+### Implementation for User Story 1
+
+- [X] T004 [P] [US1] Update icon `when` branches for `Messages` and `Connect` in `core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/navigation/TopLevelDestinationExt.kt`
+- [X] T005 [P] [US1] Update any explicit references from `Conversations`/`Connections` to `Messages`/`Connect` in `core/ui/src/commonMain/kotlin/org/meshtastic/core/ui/component/MeshtasticNavigationSuite.kt`
+- [X] T006 [P] [US1] Update default tab reference from `Connections` to `Connect` in `core/navigation/src/commonMain/kotlin/org/meshtastic/core/navigation/MultiBackstack.kt`
+- [X] T007 [P] [US1] Update references in `androidApp/src/main/kotlin/org/meshtastic/app/ui/Main.kt`
+- [X] T008 [P] [US1] Update references in `desktopApp/src/main/kotlin/org/meshtastic/desktop/Main.kt`
+- [X] T009 [P] [US1] Update references in `desktopApp/src/main/kotlin/org/meshtastic/desktop/navigation/DesktopNavigation.kt`
+
+**Checkpoint**: Tab labels display correctly β User Story 1 is visually complete
+
+---
+
+## Phase 4: User Story 2 β Navigation Still Functions After Rename (Priority: P1)
+
+**Goal**: Tapping "Messages" and "Connect" tabs navigates to the correct screens without behavior change
+
+**Independent Test**: Tap "Messages" tab β messaging screen loads; tap "Connect" tab β connection/pairing screen loads; rapid tab switching works without errors
+
+### Implementation for User Story 2
+
+- [X] T010 [US2] Update test references from `TopLevelDestination.Connections` to `TopLevelDestination.Connect` (8 locations) in `core/navigation/src/commonTest/kotlin/org/meshtastic/core/navigation/MultiBackstackTest.kt`
+
+**Checkpoint**: Navigation functions correctly with renamed enum entries β no behavioral regression
+
+---
+
+## Phase 5: User Story 3 β Deep Links and State Restoration Work (Priority: P2)
+
+**Goal**: Deep links and saved navigation state continue to route correctly after the rename
+
+**Independent Test**: Trigger a message notification β tap it β app opens to messaging screen. Kill and restore app β previously selected tab is restored.
+
+### Implementation for User Story 3
+
+No additional implementation tasks required. Deep links and state restoration use typed route objects (`ContactsRoute.Contacts`, `ConnectionsRoute.Connections`) which are NOT affected by the enum entry rename. This was confirmed in research.md (Research Task 1).
+
+**Checkpoint**: Verified by existing tests β no code changes needed for this story
+
+---
+
+## Phase 6: Polish & Cross-Cutting Concerns
+
+**Purpose**: Verification and constitution-required validation
+
+- [X] T011 [P] Run `./gradlew spotlessApply` to auto-format all touched files
+- [X] T012 [P] Run `./gradlew spotlessCheck detekt` to confirm zero lint violations
+- [X] T013 Run `./gradlew assembleDebug` to verify project compiles successfully
+- [X] T014 Run `./gradlew test allTests` to verify all existing tests pass with renamed references
+- [X] T015 Confirm no logs, telemetry, or config changes expose PII, location data, secrets, or modify `core/proto`
+
+---
+
+## Dependencies & Execution Order
+
+### Phase Dependencies
+
+- **Setup (Phase 1)**: No dependencies β can start immediately
+- **Foundational (Phase 2)**: Depends on Phase 1 (string resources must exist before enum references them)
+- **User Story 1 (Phase 3)**: Depends on Phase 2 (enum must be renamed before updating references)
+- **User Story 2 (Phase 4)**: Depends on Phase 2 (enum must be renamed before updating test references)
+- **User Story 3 (Phase 5)**: No implementation needed β verified by Phase 4 tests passing
+- **Polish (Phase 6)**: Depends on Phases 3 and 4 completion
+
+### User Story Dependencies
+
+- **User Story 1 (P1)**: Can start after Foundational (Phase 2) β No dependencies on other stories
+- **User Story 2 (P1)**: Can start after Foundational (Phase 2) β Independent of US1 (different files)
+- **User Story 3 (P2)**: Zero implementation β verified by existing route-based navigation tests
+
+### Parallel Opportunities
+
+- **Phase 3**: ALL tasks T004βT009 can run in parallel (each touches a different file)
+- **Phase 4**: T010 can run in parallel with Phase 3 tasks (different file: test vs production)
+- **Phase 6**: T011 and T012 can run in parallel with T015
+
+---
+
+## Parallel Example: User Stories 1 & 2
+
+```bash
+# After Phase 2 completes, launch ALL of these in parallel:
+Task T004: "Update TopLevelDestinationExt.kt icon branches"
+Task T005: "Update MeshtasticNavigationSuite.kt references"
+Task T006: "Update MultiBackstack.kt default tab reference"
+Task T007: "Update androidApp Main.kt references"
+Task T008: "Update desktopApp Main.kt references"
+Task T009: "Update DesktopNavigation.kt references"
+Task T010: "Update MultiBackstackTest.kt test references"
+```
+
+---
+
+## Implementation Strategy
+
+### MVP First (User Stories 1 & 2)
+
+1. Complete Phase 1: Add string resources (T001βT002)
+2. Complete Phase 2: Rename enum entries (T003)
+3. Complete Phase 3: Update all production references (T004βT009) β **in parallel**
+4. Complete Phase 4: Update test references (T010) β **parallel with Phase 3**
+5. **STOP and VALIDATE**: Run `./gradlew assembleDebug test allTests`
+6. Complete Phase 6: Polish and verification (T011βT015)
+
+### Total Effort Estimate
+
+- **Sequential execution**: 15 tasks, ~30 minutes (mechanical renames)
+- **Parallel execution**: Critical path is 6 steps (T001 β T002 β T003 β T004βT010 β T013 β T014)
+- **Risk**: Low β all changes are mechanical identifier renames with no logic changes
+
+---
+
+## Notes
+
+- [P] tasks = different files, no dependencies
+- [Story] label maps task to specific user story for traceability
+- User Story 3 requires zero implementation β validated by passing tests from US2
+- All Phase 3 tasks are mechanical `Conversations` β `Messages` and `Connections` β `Connect` identifier replacements
+- Commit after Phase 2 and after Phase 3+4 combined for clean git history
+- Old string keys (`conversations`, `connections`) are deliberately RETAINED β they serve as screen titles in other modules
Served by rngit 1.5.0 - Generated in 0.18s